package org.cmroot.certmaster.client.widgets;

import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.FocusEvent;
import com.google.gwt.event.dom.client.FocusHandler;
import com.google.gwt.event.logical.shared.OpenEvent;
import com.google.gwt.event.logical.shared.OpenHandler;
import com.google.gwt.event.logical.shared.SelectionEvent;
import com.google.gwt.event.logical.shared.SelectionHandler;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiConstructor;
import com.google.gwt.uibinder.client.UiFactory;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.Tree;
import com.google.gwt.user.client.ui.TreeItem;
import com.google.gwt.user.client.ui.Widget;
import org.cmroot.certmaster.client.AsyncCallbackParametrized;
import org.cmroot.certmaster.client.GWTClientService;
import org.cmroot.certmaster.shared.dto.X509DTO;

import java.util.HashMap;
import java.util.List;

/**
 * Copyright (c) 2010 Andrey Domas <andrey.domas at gmail.com>.
 * *
 * This file is part of certmaster.
 * *
 * Certmaster is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * *
 * Certmaster is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, see http://www.gnu.org/licenses
 * or write to the Free Software Foundation,Inc., 51 Franklin Street,
 * Fifth Floor, Boston, MA 02110-1301  USA
 */

public class PKITree  extends Composite {

    interface PKITreeUiBinder extends UiBinder<Widget, PKITree> {
    }

    private static PKITreeUiBinder _pkiTreeUiBinder = GWT.create(PKITreeUiBinder.class);

    @UiField
    Tree pkitree_gwt_widget;
    ErrorLabel errorLabel;
    SelectionHandler<TreeItem> sel_handler;

    private final static String FAKE_NODE = "__FAKE_NODE__";

    /**
     *
     * @param errorLabel - label for error messages
     * @param sel_handler - selection handler
     */
    @UiConstructor
    public PKITree(ErrorLabel errorLabel, SelectionHandler<TreeItem> sel_handler) {
        this.errorLabel = errorLabel;
        this.sel_handler = sel_handler;
        initWidget(_pkiTreeUiBinder.createAndBindUi(this));

        pkitree_gwt_widget.addOpenHandler(new OpenHandler<TreeItem>() {
            @Override
            public void onOpen(OpenEvent<TreeItem> treeItemOpenEvent) {
                TreeItem current_node = treeItemOpenEvent.getTarget();
                X509DTO cert = (X509DTO) current_node.getUserObject();
                if (current_node.getChild(0).getText().equals(FAKE_NODE + String.valueOf(cert.getCN().hashCode()))) {
                    addItems(current_node, cert);
                    current_node.getChild(0).remove();
                }
            }
        });

        if (sel_handler != null) {
            pkitree_gwt_widget.addSelectionHandler(sel_handler);
        }

    }

    public void refreshTree() {
        pkitree_gwt_widget.clear();
        addItems(null, null);
    }

    /**
     * Add branch to the tree recursively. If certs is null, then parent_node must be null too.
     * @param parent_cert - if null, them top level(with no parent) certs will be requested
     * @param treeRoot if null then first node will be created
     */
    private void addItems(TreeItem treeRoot, X509DTO parent_cert) {

        Long cert_id = (parent_cert == null) ? null : parent_cert.getId();

        GWTClientService.App.getInstance().getX509Children(cert_id, new AsyncCallbackParametrized<List<X509DTO>>(treeRoot) {

                            @Override
                            public void onFailure(Throwable caught) {
                                errorLabel.showError(caught.getMessage());
                            }

                            @Override
                            public void onSuccess(List<X509DTO> certs) {
                                for(X509DTO x : certs) {

                                    TreeItem parent_node = (TreeItem) param[0];
                                    TreeItem current_node;


                                    current_node = (parent_node == null) ?
                                            pkitree_gwt_widget.addItem(x.getCN()) :
                                            parent_node.addItem(x.getCN());
                                    current_node.setUserObject(x);
                                    if (x.getChildCount() > 0) {
                                        current_node.addItem(FAKE_NODE +
                                                String.valueOf( x.getCN().hashCode()));
                                    }
                                    addItems(current_node, x);
                                }
                            }
                        }
                );
    }

}
